#pragma once
#include<string>
#include<pthread.h>
#include <unistd.h>
#include<functional>
#include<iostream>


namespace ThreadModule
{
    static int num = 1;
    enum class STATUS
    {
        NEW,
        RUNNING,
        STOP
    };

    template<class T>
    class Thread
    {
        using func_t = std::function<void(T)>;
        static void* Routine(void* args)
        {
            Thread* t = static_cast<Thread*> (args);
            t->_fun(t->_date);
            return nullptr;
        }

        public:
        Thread(func_t fun, T date): _fun(fun), _status(STATUS::NEW), _joinable(true),_date(date)
        {
            _name = "Thread-" + std::to_string(num++);
            _pid = getpid();
        }

        bool start()
        {
            if(_status == STATUS::NEW)
            {
                _status = STATUS::RUNNING;
                int n = pthread_create(&_tid, nullptr, Routine, this);
                if(n != 0)
                {
                    return false;
                }
                return true;
            }
            return false;
        }

        bool stop()
        {
            if(_status == STATUS::RUNNING)
            {
                _status = STATUS::STOP;
                int n = pthread_cancel(_tid);
                if(n != 0)
                {
                    return false;
                }
                return true;
            }
            return false;
        }

        bool join()
        {
            if(_joinable)
            {
                int n = pthread_join(_tid, nullptr);
                if(n != 0)
                {
                    return false;
                }
                return true;
            }
            return false;
        }
        
        void detach()
        {
            unablejoin();
            pthread_detach(_tid);
        }

        std::string Name()
        {
            return _name;
        }

        void unablejoin()
        {
            _joinable = false;
        }

        ~Thread()
        {}

        private:
        std::string _name;
        pthread_t _tid;
        bool _joinable;//确定能否分离
        STATUS _status;
        pid_t _pid;
        func_t _fun;
        T _date;
    };
}